﻿// <author>Netmon Cipher Dev Team</author>
// <date>2009-07-16</date>
// <version>1.0</version>
// <summary>This contains methods to log status messages.</summary>

namespace SSLDecryptionExpert
{
    using System;
    using System.IO;
    using System.Windows.Forms;

    /// <summary>
    /// Logger Class
    /// </summary>
    public class Logger
    {
        /// <summary>
        /// StreamWriter Object.
        /// </summary>
        private StreamWriter writer;

        /// <summary>
        /// To Log data in Debug file
        /// </summary>
        private byte[] arrayLogger = new byte[32];

        /// <summary>
        /// Stores the last exception message from the DisplayException method
        /// </summary>
        private string lastError;

        /// <summary>
        /// Initializes a new instance of the Logger class.
        /// </summary>
        /// <param name="logPath">
        /// path of Log file
        /// </param>
        public Logger(string logPath)
        {
            if (Utils.CreateDirectoryIfNotExists(logPath))
            {
                this.writer = new StreamWriter(logPath, false);
                this.writer.WriteLine("-.-.-.-.-.-.- SSL Decryption Log -.-.-.-.-.-.-");
                this.writer.WriteLine();
                this.writer.WriteLine("Log Created On: " + DateTime.Now.ToString());
                this.writer.WriteLine();
            }
        }

        /// <summary>
        /// Gets the last error message reported by DisplayException
        /// </summary>
        public string LastError
        {
            get { return this.lastError; }
        }

        /// <summary>
        /// Log Message
        /// </summary>
        /// <param name="message">
        /// Message to be logged.
        /// </param>
        public void LogMessage(string message)
        {
            foreach (string line in message.Split('\n'))
            {
                this.writer.WriteLine(line);
            }

            Variables.statusMessage = message;
        }

        /// <summary>
        /// Log Message
        /// </summary>
        /// <param name="arrayToLog">
        /// Byte Array to be written.
        /// </param>
        /// <param name="keyType">
        /// Message (KeyType) to be written.
        /// </param>
        public void LogMessage(byte[] arrayToLog, string keyType)
        {
            int bytesToBeCopied = this.arrayLogger.Length;
            int startIndex = 0;

            this.writer.WriteLine();
            this.writer.WriteLine(keyType + ":");

            // Create a index for each column
            this.writer.Write("     ");
            for (int index = 0; index < this.arrayLogger.Length; index++)
            {
                this.writer.Write("{0:X2} ", index);
            }
            this.writer.WriteLine();

            // Create a separator
            this.writer.Write("     ");
            for (int index = 0; index < this.arrayLogger.Length; index++)
            {
                this.writer.Write("---");
            }
            this.writer.WriteLine();

            for (int index = 0; index < arrayToLog.Length / bytesToBeCopied; index++)
            {
                this.writer.Write("{0:X4} ", index * 0x20);
                Array.Copy(arrayToLog, startIndex, this.arrayLogger, 0, bytesToBeCopied);
                this.LogData(bytesToBeCopied);
                startIndex += bytesToBeCopied;
            }

            if (arrayToLog.Length % bytesToBeCopied != 0)
            {
                this.writer.Write("{0:X4} ", arrayToLog.Length / bytesToBeCopied * 0x20);
                bytesToBeCopied = arrayToLog.Length % bytesToBeCopied;
                Array.Copy(arrayToLog, startIndex, this.arrayLogger, 0, bytesToBeCopied);
                this.LogData(bytesToBeCopied);
            }

            this.writer.WriteLine();
        }        

        /// <summary>
        /// Displays Custom Exception/Error.
        /// </summary>
        /// <param name="exception">
        /// Message to be Displayed.
        /// </param>
        public void DisplayException(string exception)
        {
            this.writer.WriteLine("EXCEPTION: " + exception);
            this.lastError = exception;

            ////MessageBox.Show(exception, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        /// <summary>
        /// Closes the Log File.
        /// </summary>
        public void CloseLog()
        {
            this.writer.WriteLine();
            this.writer.WriteLine("-.-.-.-.-.-.- SSL Decryption Log Ends-.-.-.-.-.-.-");
            this.writer.Close();
        }

        /// <summary>
        /// Logs byte array in format of 16 bytes/line
        /// </summary>
        /// <param name="bytesToBeCopied">
        /// Bytes to be Written.
        /// </param>
        private void LogData(int bytesToBeCopied)
        {
            for(int keyIndex = 0; keyIndex < bytesToBeCopied; keyIndex++)
            {
                this.writer.Write(String.Format("{0:X2} ", this.arrayLogger[keyIndex]));
            }

            for (int keyIndex = 0; keyIndex < arrayLogger.Length - bytesToBeCopied; keyIndex++)
            {
                this.writer.Write(String.Format("   "));
            }

            for (int keyIndex = 0; keyIndex < bytesToBeCopied; keyIndex++)
            {
                if(!char.IsControl((char)this.arrayLogger[keyIndex]))
                {
                    this.writer.Write((char)this.arrayLogger[keyIndex]);
                } 
                else 
                {
                    this.writer.Write(String.Format("."));
                }
            }

            this.writer.WriteLine();
        }
    }
}
